package profile

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"math/rand"
	"time"
	"usercenter/internal/biz"
	"usercenter/internal/model"
	"usercenter/internal/svc"
	"usercenter/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/redis"
)

var (
	cacheKeyPrefix    = "user:"
	baseCacheDuration = 30 * time.Minute
)

func getCacheDuration() time.Duration {
	// 添加随机抖动防止缓存雪崩
	return baseCacheDuration + time.Duration(rand.Intn(600))*time.Second
}

type GetUserInfoLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserInfoLogic {
	return &GetUserInfoLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetUserInfoLogic) GetUserInfo(req *types.UserIdRequest) (*types.UserInfoResponse, error) {
	// 1. 参数校验
	if req.Id <= 0 {
		return nil, &biz.BizError{
			Code:    401,
			Message: "无效的ID",
		}
	}

	// 2. 尝试从缓存获取
	cacheKey := fmt.Sprintf("%s%d", cacheKeyPrefix, req.Id)
	cachedUser, err := l.getFromCache(cacheKey)
	if err == nil && cachedUser != nil {
		return l.buildSuccessResponse(cachedUser), nil
	}

	// 3. 缓存未命中，查询数据库
	user, err := l.svcCtx.UserModel.FindById(req.Id)
	if err != nil {
		if errors.Is(err, errors.New("record not found")) {
			go l.setCache(cacheKey, user) // 设置空缓存，防止缓存穿透
			return nil, errors.New("用户不存在")
		}
		l.Logger.Errorf("查询用户信息失败, userId: %d, error: %v", req.Id, err)
		return nil, errors.New("系统错误，请稍后重试")
	}

	// 4. 写入缓存
	go l.setCache(cacheKey, user)

	// 5. 返回结果
	return l.buildSuccessResponse(user), nil
}

// 从缓存获取用户信息
func (l *GetUserInfoLogic) getFromCache(key string) (*model.User, error) {
	val, err := l.svcCtx.Redis.Get(key)
	if err != nil {
		if err != redis.Nil {
			l.Logger.Errorf("获取缓存失败, key: %s, error: %v", key, err)
		}
		return nil, err
	}

	var user model.User
	if err := json.Unmarshal([]byte(val), &user); err != nil {
		l.Logger.Errorf("解析缓存数据失败, key: %s, error: %v", key, err)
		return nil, err
	}

	return &user, nil
}

// 设置缓存 (异步)
func (l *GetUserInfoLogic) setCache(key string, user *model.User) {
	duration := getCacheDuration()
	jsonData, err := json.Marshal(user)
	if err != nil {
		l.Logger.Errorf("序列化用户数据失败, userId: %d, error: %v", user.ID, err)
		return
	}

	if err := l.svcCtx.Redis.Setex(key, string(jsonData), int(duration.Seconds())); err != nil {
		l.Logger.Errorf("写入缓存失败, key: %s, error: %v", key, err)
	}
}

// 构建成功响应
func (l *GetUserInfoLogic) buildSuccessResponse(user *model.User) *types.UserInfoResponse {
	return &types.UserInfoResponse{
		Code:    200,
		Message: "success",
		Data: types.UserInfo{
			Id:        int(user.ID),
			Email:     user.Email,
			Name:      user.Name,
			Avatar:    user.Avatar,
			CreatedAt: user.CreatedAt.Format(time.RFC3339),
			UpdatedAt: user.UpdatedAt.Format(time.RFC3339),
		},
	}
}
